package vip.mtdp.asset.core.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vip.mtdp.asset.api.TradeEngineService;
import vip.mtdp.asset.api.constants.BizTypeEnum;
import vip.mtdp.asset.api.dto.TxnDTO;
import vip.mtdp.asset.api.constants.TxnStateEnum;
import vip.mtdp.asset.core.constants.PostingStateEnum;
import vip.mtdp.asset.core.dto.JournalDTO;
import vip.mtdp.asset.core.dto.PostingRuleDTO;
import vip.mtdp.asset.core.manager.JournalManager;
import vip.mtdp.asset.core.manager.PostingRuleManager;
import vip.mtdp.asset.core.manager.TxnManager;
import vip.mtdp.common.exception.AppRTException;

import java.math.BigDecimal;
import java.util.List;

/**
 * @Description
 * @Author Evans.wang
 * @since 2023/10/29 19:29
 **/
@Slf4j
@Service
public class TradeEngineServiceImpl implements TradeEngineService {

    @Autowired
    private TxnManager txnManager;

    @Autowired
    private PostingRuleManager postingRuleManager;

    @Autowired
    private JournalManager journalManager;

    @Autowired
    private PostingService postingService;


    /**
     * @param txnDTO
     */
    @Override
    @Transactional
    public void process(TxnDTO txnDTO) {
        String bizType = txnDTO.getBizType();
        if (!BizTypeEnum.support(bizType)){
            throw new AppRTException("not support bizType = " + bizType);
        }
        //保存交易
        TxnDTO mTxnDTO = txnManager.create(txnDTO);

        //查询posting rule
        List<PostingRuleDTO> postingRuleDTOList = postingRuleManager.queryByBizType(bizType);
        for (PostingRuleDTO postingRuleDTO : postingRuleDTOList){
            //生成分录
            JournalDTO journalDTO = postingRuleDTO.evaluate(txnDTO);
            //更新余额
            postingService.posting(journalDTO);
            //保存分录 && 明细
            journalManager.create(journalDTO);
        }
        //更新交易为成功
        txnManager.updateTxnState(mTxnDTO.getId(), TxnStateEnum.SUCCESS);
    }

    /**
     * 冲正
     *
     * @param txnDTO
     */

    @Override
    @Transactional
    public void reverse(TxnDTO txnDTO) {
        BigDecimal negative = new BigDecimal("-1");
        //修改源交易状态为冲正
        Long txnId = txnDTO.getRefId();
        if (txnId == null){
            throw new AppRTException("reference txn id not null");
        }
        txnManager.updateTxnState(txnId, TxnStateEnum.REVERSE);

        //保存冲正交易
        TxnDTO mTxnDTO = txnManager.create(txnDTO);

        //查询原分录 并把交易取反
        List<JournalDTO> journalDTOList = journalManager.queryByTxnId(txnId);
        if (journalDTOList != null && !journalDTOList.isEmpty()){
            for (JournalDTO journalDTO : journalDTOList) {
                journalDTO.getJournalItemDTOList().forEach(e -> {
                    e.setAmount(e.getAmount().multiply(negative));
                    e.setOpenBalance(null);
                    e.setCloseBalance(null);
                    e.setId(null);
                    e.setJournalId(null);
                });
                journalDTO.setId(null);
                journalDTO.setPostingState(PostingStateEnum.INIT.getCode());

                //更新余额
                postingService.posting(journalDTO);
                //保存分录 && 明细
                journalManager.create(journalDTO);
            }
        }

        //更新交易为成功
        txnManager.updateTxnState(mTxnDTO.getId(), TxnStateEnum.SUCCESS);
    }
}
